﻿using UnityEngine;
using System.Collections;

public class Phil : MonoBehaviour {
	
	public Utility util;
	public float dummy_dmg_received = 5f;
	public float HP = 100f;

	public int speedX = 7;
	public int speedY = 10;
	public float jumpDuration = 0.2f;
	public float playerGroundPos = 2.3f;

	//value for reference after animating/action ends
	public float default_jumpDelay = 0.1f;
	public float default_attackDelay = 0.3f;
	public float default_receivedDamageDelay = 2f;
	public int defaultSpeedX = 7;
	public int defaultSpeedY = 10;

	public float countDown = 0f;
	public float jumpDelay = 0f;
	public float attackDelay = 0f;
	public float receivedDamageDelay = 0f;
	public float offset_whenCharging = 0.5f;

	//Local Variable
	//public ArrayList actionTracker;
	public int curAction;
	public bool isKnockWall=false;
	public bool isMoving=false;
	public bool isJump=false;
	public bool isGrounded=false;
	public bool isAttacking=false;
	public bool isCharging=false;
	public bool isDamaged=false;

	public string vecticesString = "";

	//Variable for reference, DO NOT MODIFY THE VALUE
	public GameObject[] poolMagicBalls;
	private Animator animator;

	void Start () {
		animator = this.GetComponent<Animator>();
	}

	void Update () {
		/*
		 * 1 = run
		 * 2 = jump
		 * 3 = attack
		 * 4 = charge
		 */
		Vector2 newPos = transform.position;

		if(jumpDelay > 0){
			jumpDelay -= Time.deltaTime;
		}
		
		//countDown is a variable mainly used for manual-animation/move
		if(countDown > 0){
			countDown -= Time.deltaTime;
		}else{
			//if count down completed and previously was jumping
			if(isJump){
				isJump = false;
			}
		}


		if(attackDelay > 0){
			attackDelay -= Time.deltaTime;
		}

		if(isDamaged && receivedDamageDelay > 0){
			spriteBlinking();
		}

		//##############################################
		//KEY EVENTS
		//##############################################
		//when no key is pressed
		if(Input.anyKey == false){
			curAction = 0;
		}

		if(!isCharging){
			if( Input.GetKey(KeyCode.LeftArrow) ){
				// "flip" the sprite to left with x = -1
				transform.localScale = new Vector2(-1f, 1f);
				isMoving = true;
			}else if( Input.GetKey(KeyCode.RightArrow) ){
				// "flip" the sprite to right with x = 1
				transform.localScale = new Vector2(1f, 1f);
				isMoving = true;
			}else{
				isMoving = false;
			}
		}

		//Physics2D.Linecast(

		//we use !Input.GetKey(KeyCode.S) instead of !isCharging because isCharging is only set AFTERWARDS and further from realtime
		if( Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.S) ){
			//if sprite's Y is touching the ground
			if(isGrounded){
				isJump = true;
				isGrounded = false;
				countDown = jumpDuration;
			}
		}

		//animation 3
		if( Input.GetKey(KeyCode.D) ){
			isAttacking=true;
		}else{
			isAttacking=false;
		}

		//animation 4
		if( Input.GetKey(KeyCode.S) ){
			isCharging = true;
		}else{
			isCharging = false;
		}

		//for changing animation sprite & position
		//only use "jump" animation if S & D are not pressed
		if(isCharging){
			curAction = 4;
			chargingModeOn();

			newPos.x += (speedX*Time.deltaTime)*transform.localScale.x;

			if(!isGrounded){
				newPos.y -= ( (speedY/2)*Time.deltaTime);
			}
		}else{
			//Below needs to be separated because there can be only 1 animation running
			//yet other behaviour can be combined (eg. jump + moving forward + attacking)
			//for animation only
			if(isAttacking){
				curAction = 3;
			}else if(isJump || !isGrounded) {
				curAction = 2;
			}else if(isMoving){
				curAction = 1;
			}

			//for changing position only
			if(isAttacking){
				shootMagicBall();
			}
			if(isJump || !isGrounded) {
				if(isJump){
					newPos.y += (speedY*Time.deltaTime);
				}else if(!isGrounded){
					newPos.y -= (speedY*Time.deltaTime);
				}
			}
			if(isMoving){
				newPos.x += (speedX*Time.deltaTime)*transform.localScale.x;
			}
			chargingModeOff();
		}


		transform.position = newPos;

		animator.SetInteger("characterAction", curAction);
		setBoxColliderBasedOnActionType();
	}
	/*
	//collision events have: Enter2D, Stay2D, Exit2D
	//May need to use OnCollisionStay2D() for constant damage
	void OnCollisionEnter2D(Collision2D collisionObj){
		if( "Structures".Equals(collisionObj.gameObject.tag) && "Ground".Equals(collisionObj.gameObject.name) ){
			isGrounded = true;
			if(isFalling){
				jumpDelay = default_jumpDelay;
				isFalling = false;
			}

		}else if(! "Structures".Equals(collisionObj.gameObject.tag) ){
			Debug.Log ("OnCollisionEnter2D, collisionObj tag: " + collisionObj.gameObject.tag);
			if(isCharging){
			}else{
				receivedDamageIfCollideMonster(collisionObj);
			}
		}
	}

	void OnCollisionStay2D(Collision2D collisionObj){
		receivedDamageIfCollideMonster(collisionObj);
	}
	*/

	void OnCollisionEnter2D(Collision2D collidedObj){
		string collidedObjTagName = collidedObj.gameObject.tag;
		if( "Structures".Equals(collidedObjTagName) ){
			if("Ground".Equals(collidedObj.gameObject.name) ){
				if(!isGrounded){
					jumpDelay = default_jumpDelay;
					isGrounded = true;
				}
			}else if(collidedObj.gameObject.name.StartsWith("InvisibleWall")){
				isKnockWall = true;
			}
		}else if(! "Structures".Equals(collidedObjTagName) ){
			Debug.Log ("OnCollisionEnter2D, collisionObj tag: " + collidedObjTagName);
			if(isCharging){
				//TODO: decrease mob HP
			}else{
				//TODO: decrease player HP
				receivedDamageIfCollideMonster(collidedObj);
			}
		}
		//isKnockWall = false;
	}
	/*
	void OnTriggerStay2D(Collider2D collidedObj){
		receivedDamageIfCollideMonster(collidedObj);

		if(collidedObj.gameObject.name.StartsWith("InvisibleWall")){
			isKnockWall = true;
		}else{
			isKnockWall = false;
		}
	}
	*/
	void OnTriggerExit2D(Collider2D collidedObj){
		/*
		if(collidedObj.gameObject.name.StartsWith("InvisibleWall")){
			isKnockWall = false;
		}
		*/
	}

	void chargingModeOn(){
		speedY = defaultSpeedY/2;
		speedX = defaultSpeedX*3;
	}
	
	void chargingModeOff(){
		speedY = defaultSpeedY;
		speedX = defaultSpeedX;
	}

	void shootMagicBall(){
		if(attackDelay > 0){
			//Don't allow shoot if delay haven't end yet
			//Note: delay will decrease in update()
			return;
		}

		int direction = 1;
		if(transform.localScale.x < 0){
			direction = -1;
		}
		

		Vector2 posInFrontOfPlayer = new Vector2(transform.position.x+ (1.5f*direction) , transform.position.y+0.63f);
		MagicBall tempScript;
		foreach(GameObject obj in poolMagicBalls){
			tempScript = obj.GetComponent<MagicBall>();
			if(!tempScript.isVisible){
				tempScript.recreateInFrontOfPlayer(posInFrontOfPlayer, direction);
				attackDelay = default_attackDelay;
				break;
			}
		}
	}

	int playerJump(){
		int curAction = 0;

		if(!isJump && isGrounded){
			
			//if jump jumpDelay ends
			if(jumpDelay <= 0f){
				curAction = 2;
				isJump = true;
				isGrounded = false;
				countDown = jumpDuration;
				//jumpDelay = default_jumpDelay;
			}else{
				//if jump jumpDelay haven't end
				if( Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow) ){
					curAction = 1;
				}else{
					curAction = 0;
				}
			}
		}else{
			curAction = 2;
		}
		return curAction;
	}

	void receivedDamageIfCollideMonster(Collision2D collidedObj){
		if( "Monsters".Equals(collidedObj.gameObject.tag) && !isDamaged ){
			receivedDamageDelay = default_receivedDamageDelay;
			isDamaged = true;
			HP -= dummy_dmg_received;
			util.displayDamageNumber(dummy_dmg_received.ToString(), new Vector2(transform.position.x, transform.position.y+1.1f));
		}
	}

	void spriteBlinking(){
		int blinking = (int) (receivedDamageDelay/0.1f);

		//if is even number
		if(blinking % 2 == 1){
			//dark gray color
			GetComponent<SpriteRenderer>().color = Color.gray;
		}else{
			//white/original color
			GetComponent<SpriteRenderer>().color = Color.white;
		}

		receivedDamageDelay -= Time.deltaTime;
		if(receivedDamageDelay <= 0){
			isDamaged = false;
		}
	}

	void setBoxColliderBasedOnActionType(){
		GetComponent<BoxCollider2D>().center = new Vector2(0f, 0f);
		switch(curAction){
		case 0:
			GetComponent<BoxCollider2D>().size = new Vector2(1.03f, 1.85f);
			break;
		case 1: //run
			GetComponent<BoxCollider2D>().size = new Vector2(1.82f, 1.45f);
			GetComponent<BoxCollider2D>().center = new Vector2(-0.02f, -0.19f);
			break;
		case 2:	//jump
		case 3: //attack
			GetComponent<BoxCollider2D>().size = new Vector2(1.05f, 1.85f);
			break;
		case 4:
			GetComponent<BoxCollider2D>().size = new Vector2(3.74f, 1.85f);
			break;
		}
	}
}//class
